package com.lemzdo.mail.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lemzdo.common.utils.PageUtils;
import com.lemzdo.common.utils.Query;
import com.lemzdo.mail.product.dao.CategoryDao;
import com.lemzdo.mail.product.entity.CategoryEntity;
import com.lemzdo.mail.product.service.CategoryBrandRelationService;
import com.lemzdo.mail.product.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {


   /* @Autowired //注入dao操作数据
    private CategoryDao categoryDao;*/
   @Autowired
   private CategoryBrandRelationService categoryBrandRelationService;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 查询所有的分类，以树形结构存储
     *
     * @return 所有的分类
     */
    @Override
    public List<CategoryEntity> listWithTree() {

        //1.查询出所有分类 可以注入dao操作 此处逆向工程提供了ServiceImpl，泛型就是需要的dao
        //ServiceImpl里面有个baseMapper 就是CategoryDao

        List<CategoryEntity> entityList = baseMapper.selectList(null);
        //2.组装成父子的树形结构

        //2.1找到所有的一级分类（父id是0的即没有父亲）
        /*entityList.stream().filter((categoryEntity)->{
            return categoryEntity.getParentCid()==0; }).collect(Collectors.toList());*/

        //一个参数 省略小括号， 一条return 省略大括号和return
        List<CategoryEntity> menuLv1 = entityList.stream().filter(categoryEntity ->//过滤器 只需要父id等于0的
                categoryEntity.getParentCid() == 0).peek((menu) -> {//.peek
            menu.setChildren(getChildren(menu, entityList));//给每个一级分类 赋值自定义的属性children再映射回去
        }).sorted(Comparator.comparingInt(menu -> menu.getSort() == null ? 0 : menu.getSort()))//排序
                .collect(Collectors.toList());//用list收集起来

        return menuLv1;
    }

    /**
     * 自定义一个方法 递归查询子分类
     *
     * @param entity     需要查询子分类的当前分类
     * @param entityList 所有的分类
     * @return 返回子分类
     */
    private List<CategoryEntity> getChildren(CategoryEntity entity, List<CategoryEntity> entityList) {

        //通过流 找出所有菜单中 当前菜单的子菜单
        List<CategoryEntity> children = entityList.stream().filter((categoryEntity) -> {
            return categoryEntity.getParentCid().equals(entity.getCatId());//所有菜单中 父id 等于当前菜单id的 就是子菜单
        }).peek((menu) -> {
            menu.setChildren(getChildren(menu, entityList));//给查询出来的子菜单 递归再查询子菜单 赋值放入children中
        }).sorted(Comparator.comparingInt(menu -> (menu.getSort() == null ? 0 : menu.getSort())))
                .collect(Collectors.toList());//排序 并存入list


        return children;
    }

    /**
     * 自定义的增强过的删除方法
     *
     * @param asList 需要删除的id的list集合
     */
    @Override
    public void removeMenuByIds(List<Long> asList) {

        //todo 检查

        //批量删除
        baseMapper.deleteBatchIds(asList);

    }

    /**
     * 根据属性分组表的三级分类id查询出三级分类完整路径 [父/子/孙]
     *
     * @param catelogId 属性分组表的三级分类id 也就是 分类表的id
     * @return 三级分类完整路径 [父，子，孙]
     */
    @Override
    public Long[] findCatelogPath(Long catelogId) {

        List<Long> paths = new ArrayList<>();
        //由于当前分类 可能有父分类， 父分类可能有爷分类 所以需要一个递归方法来查询出所有的父id并收集起来
        //调用递归方法 完成功能
        List<Long> parentPath = getParentPath(catelogId, paths);

        //递归回来收集的是逆序的[孙，子，父] 需要逆序
        Collections.reverse(parentPath);

        return parentPath.toArray(new Long[0]);
    }

    /**
     * 自定义递归方法来依次向上查询父路径 并全部收集返回
     * @param catelogId 当前分类id
     * @param paths list集合 用来存放路径
     * @return 存放了所有父路径的list 逆序的[225,20,2] 【华为，国产手机，手机】
     */
    public List<Long> getParentPath(Long catelogId,List<Long> paths) {
        //收集当前节点id
        paths.add(catelogId);

        //根据属性分组表的catelogId也就是 三级分类表的id 查询出当前分类的信息
        CategoryEntity categoryEntity = this.getById(catelogId);

        //判断有没有父亲 并收集
        if(categoryEntity.getParentCid()!=0){
            //有父亲 递归调用本方法 再次收集当前结点（父节点）id，并查询信息判断是否有爷爷节点
            getParentPath(categoryEntity.getParentCid(),paths);
        }

        //递归结束 没有父节点了 返回
        return paths;
    }

    /**
     *  级联更新所有关联的数据
     * @param category 需要更新的数据
     */
    @Override
    public void updateCascade(CategoryEntity category) {

        //先更新自己
        this.updateById(category);

        //判断当前更新 是否更新了冗余数据（例如分类名字）
        if(!StringUtils.isEmpty(category.getName())){
            //分类名非空 说明此次更新了名字 需要更新其他关联表中的数据(品牌分类关系表)
            //可以使用service自带的update 也可以自定义mapper方法 直接手写sql语句 Brand使用的update 这里手写sql
            this.baseMapper.updateCategoryNameByCategoryId(category.getCatId(),category.getName());


            //todo 更新其他关联表中的品牌信息
        }

    }
}